﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
using CrawlerCore;
using HtmlAgilityPack;

namespace WCrawlerLib
{
    public abstract class BrowserSession_phpBB : BrowserSession_Forum
    {
        public BrowserSession_phpBB()
        {
            ForumTypeId = enumForumType.phpBB;
        }

        #region Properties
        
        public string sid
        {
            get
            {
                string value = "";
                try
                {
                    foreach (Cookie cook in Cookies)
                    {
                        if (cook.Name.Contains("sid"))
                        {
                            value = cook.Value;
                            break;
                        }
                    }
                    //HtmlNode node = HtmlDoc.DocumentNode.SelectSingleNode(".//input[@type='hidden' and @name='loggedinuser']");
                    //if (node != null)
                    //    value = node.Attributes["value"].Value;
                }
                catch
                {
                }
                return value;
            }
        }
        #endregion

        /// <summary>
        /// Get user id
        /// </summary>
        /// <param name="forumUrl"></param>
        /// <param name="userName"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        public override int GetUserId(string forumUrl, string userName)
        {
            //*********************************************************************************
            //Get User Id
            //*********************************************************************************
            int userId= -1;
            string profileUrl = forumUrl + "/" + "ucp.php";
            HtmlDocument doc = Get(profileUrl);
            string htmlContent = HttpUtility.HtmlDecode(doc.DocumentNode.InnerHtml);
            string pattern = @"search\.php\?author_id=(?<value>[0-9]+)";
            Regex r = new Regex(pattern);
            Match m = r.Match(htmlContent);
            if (m.Success){
                userId = int.Parse(m.Result("${value}"));
            }
            return userId;
        }

        /// <summary>
        /// enumPost.NewThread, postParams, subject, message, fId, icon, tagList
        /// </summary>
        /// <param name="postType"></param>
        /// <param name="postParams"></param>
        /// <param name="pars"></param>
        /// <returns></returns>
        public string InitPostParams(enumPost postType, string postParams, params string[] pars)
        {
            Dictionary<string, string> paramDict = new Dictionary<string, string>();
            if (postType == enumPost.Login)
            {
                //=============================================================================
                //LOGIN PARAMS
                paramDict.Add("[username]", pars[0]);
                paramDict.Add("[passwor]", pars[1]);
                paramDict.Add("[login]", "Login");
                paramDict.Add("[autologin]", "on");
                //for phpbb2
                paramDict.Add("[sid]", "");
                paramDict.Add("[redirect]", "");
            }
            else if (postType == enumPost.NewThread)
            {
                //=============================================================================
                //NEWTHREAD POST PARAMS
                paramDict.Add("[icon]", pars[3]);
                paramDict.Add("[subject]", pars[0]);
                //paramDict.Add("[addbbcode20]", "100");
                paramDict.Add("[message]", pars[1].Replace("&", "%26"));
                //paramDict.Add("[lastclick]", HtmlDoc.GetValueInInputTag("hidden", "name", "lastclick"));
                paramDict.Add("[post]", "Submit");
                //paramDict.Add("[attach_sig]", "on");
                //paramDict.Add("[creation_time]", HtmlDoc.GetValueInInputTag("hidden", "name", "creation_time"));
                //paramDict.Add("[form_token]", HtmlDoc.GetValueInInputTag("hidden", "name", "form_token"));
            }
            else if (postType == enumPost.EditPost)
            {
                //=============================================================================
                //EDIT POST PARAMS
                paramDict.Add("[icon]", pars[2]);
                paramDict.Add("[subject]", pars[0]);
                //paramDict.Add("[addbbcode20]", "100");
                paramDict.Add("[message]", pars[1].Replace("&", "%26"));
                //paramDict.Add("[lastclick]", HtmlDoc.GetValueInInputTag("hidden", "name", "lastclick"));
                paramDict.Add("[edit_post_message_checksum]", HtmlDoc.GetValueInInputTag("hidden", "name", "edit_post_message_checksum"));
                paramDict.Add("[edit_post_subject_checksum]", HtmlDoc.GetValueInInputTag("hidden", "name", "edit_post_subject_checksum"));
                paramDict.Add("[post]", "Submit");
                //paramDict.Add("[attach_sig]", "on");
                //paramDict.Add("[creation_time]", HtmlDoc.GetValueInInputTag("hidden", "name", "creation_time"));
                //paramDict.Add("[form_token]", HtmlDoc.GetValueInInputTag("hidden", "name", "form_token"));
            }
            else
            {
                //=============================================================================
                //REPLY POST PARAMS
                
            }

            //=============================================================================
            //SAME PARAMS
            paramDict.Add("[addbbcode20]", "100");
            paramDict.Add("[lastclick]", HtmlDoc.GetValueInInputTag("hidden", "name", "lastclick"));
            paramDict.Add("[attach_sig]", "on");
            paramDict.Add("[creation_time]", HtmlDoc.GetValueInInputTag("hidden", "name", "creation_time"));
            paramDict.Add("[form_token]", HtmlDoc.GetValueInInputTag("hidden", "name", "form_token"));

            foreach (KeyValuePair<string, string> par in paramDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        ///// <summary>
        ///// Init params of new thread
        ///// </summary>
        ///// <param name="postParams"></param>
        ///// <param name="subject"></param>
        ///// <param name="message"></param>
        ///// <param name="fId"></param>
        ///// <param name="tagList"></param>
        ///// <returns></returns>
        //public override string InitNewThreadParams(string postParams, params string[] values)// , string subject, string message, string fId, string icon, string tagList)
        //{
        //    //========================================================================
        //    //Init new thread params
        //    Dictionary<string, string> paramDict = new Dictionary<string, string>();
        //    paramDict.Add("[icon]", values[3]);
        //    paramDict.Add("[subject]", values[0]);
        //    paramDict.Add("[addbbcode20]", "100");
        //    paramDict.Add("[message]", values[1].Replace("&", "%26"));
        //    paramDict.Add("[lastclick]", HtmlDoc.GetValueInInputTag("hidden", "name", "lastclick"));
        //    paramDict.Add("[post]", "Submit");
        //    paramDict.Add("[attach_sig]", "on");
        //    paramDict.Add("[creation_time]", HtmlDoc.GetValueInInputTag("hidden", "name", "creation_time"));
        //    paramDict.Add("[form_token]", HtmlDoc.GetValueInInputTag("hidden", "name", "form_token"));
        //    foreach (KeyValuePair<string, string> par in paramDict)
        //    {
        //        if (postParams.Contains(par.Key))
        //            postParams = postParams.Replace(par.Key, par.Value);
        //    }
        //    return postParams;
        //}

        /// <summary>
        /// Login in a forum. If susscessful set _isLogged = true, else false
        /// </summary>
        public override bool DoLogin(string forumUrl, string loginUrl, string postParams, string username, string password)
        {
            bool loginStatus = false;
            try
            {
                //Init login params
                InitPostParams(enumPost.Login, username, password);
                loginUrl = GeneralClass.GetFullUrl(forumUrl, loginUrl);
                Post(loginUrl);

                string content = HtmlDoc.DocumentNode.InnerHtml.ToLower();
                List<string> key = new List<string>();

                string pattern = @"(thank you|successful(ly|) logged in|log out|" + username + ")";

                Regex r = new Regex(pattern);
                MatchCollection m = r.Matches(content);

                //If count > 1 successfully log in
                if (m.Count >= 1)
                {
                    loginStatus = true;
                }
            }
            catch (WebException we)
            {
                throw we;
                //Console.WriteLine(e.Message);
                //loginStatusId = 2;
            }
            catch (Exception ex)
            {
                throw ex;
                //Console.WriteLine(e.Message);
                //loginStatusId = 2;
            }
            return loginStatus;
        }

        /// <summary>
        /// Post a new thread
        /// .//div[contains(@id,'post_message')]
        /// </summary>
        /// <param name="forumUrl"></param>
        /// <param name="newThreadurl"></param>
        /// <param name="postParams"></param>
        /// <param name="subject"></param>
        /// <param name="message"></param>
        /// <param name="fId"></param>
        /// <param name="tagList"></param>
        /// <returns></returns>
        public override void PostNewThread(string forumUrl, string newThreadurl, string postParams, string subject, string message, string fId, string icon, string tagList, string prefixId)
        {
            //string postNewThreadUrl = forumUrl + "/" + "newthread.php?do=newthread&f=" + fId.ToString() + "&s=" + SessionHash;
            newThreadurl = newThreadurl.Replace("[fid]", fId.ToString());
            string postNewThreadUrl = forumUrl + "/" + newThreadurl;
            Get(postNewThreadUrl);

            postNewThreadUrl = forumUrl + "/" + newThreadurl + "&sid=" + sid;
            //Get POST Params 
            //_postParams = InitNewThreadParams(postParams, subject, message, fId, icon, tagList);
            _postParams = InitPostParams(enumPost.NewThread, postParams, subject, message, fId, icon, tagList);
            Post(postNewThreadUrl);
        }

        ///// <summary>
        ///// Init params of a post update
        ///// Notes: "securityToken" and "relpath" not get direct in current _htmDoc
        ///// </summary>
        ///// <param name="postParams"></param>
        ///// <param name="message"></param>
        ///// <returns></returns>
        //public string InitPostUpdateParams(string postParams, params string[] pars)//string subject, string message, string icon)
        //{
        //    //========================================================================
        //    //Init new thread params
        //    Dictionary<string, string> paramDict = new Dictionary<string, string>();
        //    paramDict.Add("[icon]", pars[2]);
        //    paramDict.Add("[subject]", pars[0]);
        //    paramDict.Add("[addbbcode20]", "100");
        //    paramDict.Add("[message]", pars[1].Replace("&", "%26"));
        //    paramDict.Add("[lastclick]", HtmlDoc.GetValueInInputTag("hidden", "name", "lastclick"));
        //    paramDict.Add("[edit_post_message_checksum]", HtmlDoc.GetValueInInputTag("hidden", "name", "edit_post_message_checksum"));
        //    paramDict.Add("[edit_post_subject_checksum]", HtmlDoc.GetValueInInputTag("hidden", "name", "edit_post_subject_checksum"));
        //    paramDict.Add("[post]", "Submit");
        //    paramDict.Add("[attach_sig]", "on");
        //    paramDict.Add("[creation_time]", HtmlDoc.GetValueInInputTag("hidden", "name", "creation_time"));
        //    paramDict.Add("[form_token]", HtmlDoc.GetValueInInputTag("hidden", "name", "form_token"));

        //    foreach (KeyValuePair<string, string> par in paramDict)
        //    {
        //        if (postParams.Contains(par.Key))
        //            postParams = postParams.Replace(par.Key, par.Value);
        //    }
        //    return postParams;
        //}

        ///// <summary>
        ///// Get group title include titles of subforums 
        ///// vBulletin3x: .//table[@id='threadslist']/tbody/tr[./td[contains(@id, 'td_threadtitle')]]
        ///// vBulletin4x: .//li[contains(@id,'thread')]/div
        ///// </summary>
        ///// <param name="forum"></param>
        ///// <param name="xPath"></param>
        ///// <returns></returns>
        //public override DataTable SearchNewestThread(string forumUrl, string statisticUrl, DataTable table)
        //{
        //    statisticUrl = GeneralClass.GetFullUrl(forumUrl, statisticUrl);
        //    Get(statisticUrl);
        //    DataRow row = SearchNewestThread_DataRow(forumUrl, HtmlDoc, table);
        //    table.Rows.Add(row);
        //    return table;

        //}
        /// <summary>
        /// Get group title include titles of subforums 
        /// vBulletin3x: .//table[@id='threadslist']/tbody/tr[./td[contains(@id, 'td_threadtitle')]]
        /// vBulletin4x: .//li[contains(@id,'thread')]/div
        /// </summary>
        /// <param name="forum"></param>
        /// <param name="xPath"></param>
        /// <returns></returns>
        public override DataTable SearchForumThreads(string forumUrl, string statisticUrl, string xPath_Paging, DataTable table, bool isPaging, bool isGetFirstThreads)
        {
            xPath_Paging = @".//a[contains(@href, '&page=')]";
            table = base.SearchForumThreads(forumUrl, statisticUrl, xPath_Paging, table, isPaging, isGetFirstThreads);
            return table;
        }

        public override bool PostReply(string topicUrl, string forumUrl, string message)
        {
            throw new NotImplementedException();
        }

        public override bool PostNewReply(string forumUrl, string topicUrl, string newReplyUrl, string postParams, string message)
        {
            throw new NotImplementedException();
        }

        public override bool EditPost(string forumUrl, string topicUrl, string postId, string editParams, string subject, string message, string updateReason, string icon)
        {
            throw new NotImplementedException();
        }

        public override List<DataRow> SearchThreadsByPaging(string forumUrl, HtmlDocument doc, DataTable table)
        {
            throw new NotImplementedException();
        }

        public override string SearchThreadsInTopic(string postTitle, string topicUrl, string searchTopic_xPath, string username)
        {
            throw new NotImplementedException();
        }

        public override string[] GetThreadPostNum(HtmlDocument doc)
        {
            throw new NotImplementedException();
        }

        public override string FValue_Pattern()
        {
            throw new NotImplementedException();
        }
    }
}